package many_one

import (
	"producter_consumer/out"
	"sync"
)

// 多个生产者一个消费者

type Task struct {
	ID int64
}

// 运行
func (t *Task) run() {
	out.Println(t.ID)
}

// 定义channel,并给一个缓存为 10
var taskCh = make(chan Task, 10)

const taskNum int64 = 10000
const nums = 100

//
/**
生产者,这里有多个生产者的情况下,传入数据
startNum int64 开始数字
nums int64 总数字
*/
func producer(wo chan<- Task, startNum int64, nums int64) {
	// 定义
	var i int64
	for i = startNum; i < startNum+nums; i++ {
		t := Task{
			ID: i,
		}
		wo <- t
	}
}

// 定义一个消费者-这里多个消费者的情况下
func consumer(ro <-chan Task) {
	// 遍历, 这里在多个协程一起运行的情况下,有100个协程同时访问一个值
	for t := range ro {
		if t.ID != 0 {
			t.run()
		}
	}
}

// ExecWg 下面使用 waitgroup 来处理
func ExecWg() {
	wg := &sync.WaitGroup{}
	pwg := &sync.WaitGroup{}

	// 生产者 - 多个生产者的情况
	var i int64
	for i = 0; i < taskNum; i += nums {
		if i >= taskNum {
			break
		}
		wg.Add(1)
		pwg.Add(1)
		// 这里需要把 i 作为参数传入协程进行使用
		go func(i int64) {
			defer wg.Done()
			defer pwg.Done()
			producer(taskCh, i, nums)
		}(i)
	}

	//   单个生产者的情况
	//go func() {
	//	defer wg.Done()
	//	producer(taskCh)
	//}()
	wg.Add(1) // 这里添加协程的数量 - 生产者1个
	// 消费者 - 一个消费者的情况
	go func() {
		defer wg.Done()
		consumer(taskCh)
	}()

	// 这里消费者的wg数量也需要变更

	// 这里是多个消费者的情况下,需要循环遍历多个消费者的情况
	//var i int64
	//for i = 0; i < taskNum; i++ {
	//	if i%100 == 0 {
	//		wg.Add(1) // 每次起一个协程,计数器就需要加1
	//		go func() {
	//			defer wg.Done()
	//			consumer(taskCh)
	//		}()
	//	}
	//}

	// 这里在两个协程执行完成以后就结束wait
	wg.Wait()
	out.Println("执行成功")
}
